package org.awa.demo.opencv.gltf;


import de.javagl.jgltf.model.AccessorModel;
import de.javagl.jgltf.model.GltfModel;
import de.javagl.jgltf.model.MeshModel;
import de.javagl.jgltf.model.MeshPrimitiveModel;
import de.javagl.jgltf.model.io.GltfModelReader;
import lombok.extern.slf4j.Slf4j;
import org.awa.demo.opencv.bean.gltf.PrimitiveBean;
import org.locationtech.jts.math.Vector3D;
import org.springframework.stereotype.Component;

import java.io.File;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Component
public class GltfEncoder {

    public List<PrimitiveBean> encode(File file) throws Exception {
        List<PrimitiveBean> resultList = new ArrayList<>();

        // 1. 创建 GLTF 读取器
        GltfModelReader reader = new GltfModelReader();

        // 2. 加载 GLTF/GLB 文件
        GltfModel model = reader.read(file.toURI());

        // 3. 解析数据
        log.info("场景数量: " + model.getSceneModels().size());
        log.info("网格数量: " + model.getMeshModels().size());
        log.info("材质数量: " + model.getMaterialModels().size());

        for (MeshModel meshModel : model.getMeshModels()) {
            log.info("Mesh: " + meshModel.getName());
            List<MeshPrimitiveModel> meshPrimitiveModels = meshModel.getMeshPrimitiveModels();
            log.info("面数量: " + meshPrimitiveModels.size());
            for (MeshPrimitiveModel primitiveModel : meshPrimitiveModels) {
                PrimitiveBean primitiveBean = new PrimitiveBean();
                primitiveBean.setName(meshModel.getName());
                List<float[]> pointList = new ArrayList<>();

                AccessorModel accessorModel = primitiveModel.getAttributes().get("POSITION");
                if(accessorModel != null) {
                    ByteBuffer bufferData = accessorModel.getBufferViewModel().getBufferModel().getBufferData();
                    int componentCount = accessorModel.getComponentSizeInBytes();
                    int stride = accessorModel.getByteStride() > 0 ? accessorModel.getByteStride() : componentCount * Float.BYTES;
                    int byteOffset = accessorModel.getBufferViewModel().getByteOffset();
                    log.info("ByteBuffer capacity: " + bufferData.capacity());
                    log.info("ByteBuffer length: " + accessorModel.getBufferViewModel().getByteLength() + " - "+ accessorModel.getBufferViewModel().getByteOffset());
                    log.info("accessorModel count: " + accessorModel.getCount());
                    log.info("componentCount: " + componentCount);
                    log.info("stride: " + stride);
                    log.info("byteOffset: " + byteOffset);

                    log.info("顶点数量: " + accessorModel.getCount());
                    for (int i = 0; i < accessorModel.getCount(); i++) {
                        log.info(">>>>>>>>>>>>> " + i + " >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
                        float float1 = bufferData.getFloat(byteOffset + i * stride + 0 * Float.BYTES);
                        float float2 = bufferData.getFloat(byteOffset + i * stride + 1 * Float.BYTES);
                        float float3 = bufferData.getFloat(byteOffset + i * stride + 2 * Float.BYTES);

                        log.info("顶点坐标示例: " + Arrays.toString(new float[]{
                                float1,float2,float3
                        }));

                        pointList.add(SoundUtil.createPoint(float1, float2, float3));
                    }
                }
                primitiveBean.setPointList(pointList);

                //转换成blender的右手坐标系，获取各个面。因为blender的坐标系更符合人的思维惯性，有利于后续的分析
                List<float[]> blenderPointList = primitiveBean.getPointList().parallelStream().map(point -> {
                    return SoundUtil.toBlenderCrs(point);
                }).collect(Collectors.toList());
                primitiveBean.setBlenderPointList(blenderPointList);

                resultList.add(primitiveBean);
            }
        }

        return resultList;
    }
}
